package com.abl.core.service.mt.impl;


import com.abl.core.common.cache.Cache;
import com.abl.core.common.security.AuthUser;
import com.abl.core.common.util.*;
import com.abl.core.domain.db.MtRoom;
import com.abl.core.domain.db.MtRoomApply;
import com.abl.core.domain.db.MtRoomInOut;
import com.abl.core.domain.db.SysUser;
import com.abl.core.domain.mt.MtRoomApplyVo;
import com.abl.core.domain.project.MSG;
import com.abl.core.domain.project.PageSearch;
import com.abl.core.domain.project.ServiceException;
import com.abl.core.mybatis.mapper.MtRoomApplyMapper;
import com.abl.core.mybatis.mapper.MtRoomInOutMapper;
import com.abl.core.mybatis.mapper.MtRoomMapper;
import com.abl.core.mybatis.mapper.SysUserMapper;
import com.abl.core.service.mt.MtRoomService;
import com.abl.core.service.sys.SysDictService;
import com.alibaba.fastjson2.JSONObject;
import com.freewayso.image.combiner.ImageCombiner;
import com.freewayso.image.combiner.enums.OutputFormat;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import static com.abl.core.domain.db.table.MtRoomApplyTableDef.MT_ROOM_APPLY;
import static com.abl.core.domain.db.table.MtRoomTableDef.MT_ROOM;
import static com.abl.core.domain.db.table.SysUserTableDef.SYS_USER;

/**
 * 会议室相关功能服务类
 */
@Slf4j
@Service
public class MtRoomServiceImpl implements MtRoomService {
    @Resource
    private Cache<String> cache;

    @Resource
    private MtRoomMapper mtRoomMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private MtRoomInOutMapper inOutMapper;

    @Resource
    private MtRoomApplyMapper mtRoomApplyMapper;

    @Resource
    private SysDictService dictService;

    //申请会议室资格
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addApply(MtRoomApply param) {
        AuthUser currentUser = AuthKit.mastLogin();

        //结束时间至少要晚于当前日期 xxx 天
        // 获取当前日期
        Date currentDate = new Date();
        // 解析参数中的结束时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date endDate = null;
        try {
            endDate = sdf.parse(param.getApplyCloseTime());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        // 获取 afterDay 天后的日期
        int afterDay = Integer.parseInt(dictService.getString("apply_close_time_after", "0"));
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, afterDay);
        Date afterDaysLater = calendar.getTime();
        // 检查结束时间是否晚于 afterDaysLater
        if (!endDate.after(afterDaysLater)) {
            throw new ServiceException("结束时间至少要晚于当前日期" + afterDay + "天");
        }

        //校验是否有待审核记录
        QueryWrapper check1 = QueryWrapper.create().from(MtRoomApply.class).where(MT_ROOM_APPLY.USER_ID.eq(currentUser.getUserId())).where(MT_ROOM_APPLY.APPLY_STATUS.eq("0")).where(MT_ROOM_APPLY.DEL.eq("0")).limit(1);
        MtRoomApply mtRoomApplyCheck1 = mtRoomApplyMapper.selectOneByQuery(check1);
        if (mtRoomApplyCheck1 != null) {
            throw new ServiceException(MSG.MT_ROOM_APPLY_HAS_TO_BE_REVIEWED);
        }
        // 校验是否有通过审核并且没到期的记录
        QueryWrapper check2 = QueryWrapper.create().from(MtRoomApply.class).where(MT_ROOM_APPLY.USER_ID.eq(currentUser.getUserId())).where(MT_ROOM_APPLY.APPLY_STATUS.eq("1")).where(MT_ROOM_APPLY.APPLY_CLOSE_TIME.ge(new Date())).where(MT_ROOM_APPLY.DEL.eq("0")).limit(1);
        MtRoomApply mtRoomApplyCheck2 = mtRoomApplyMapper.selectOneByQuery(check2);
        if (mtRoomApplyCheck2 != null) {
            throw new ServiceException(MSG.MT_ROOM_APPLY_HAS_MT_AUTH);
        }

        //填充数据
        param.setApplyStatus("0");
        param.setUserId(currentUser.getUserId());

        int i = mtRoomApplyMapper.insertSelective(param);
        return true;
    }

    //审批操作
    @Override
    public boolean applyRoom(MtRoomApply param) {
        mtRoomApplyMapper.update(param);
        return true;
    }

    //修改会议号
    @Override
    public boolean updateRoomCode(MtRoomApply param) {
        mtRoomApplyMapper.update(param);
        return true;
    }

    //开启会议
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MtRoom openMtRoom(MtRoom param) {
        AuthUser authUser = AuthKit.mastLogin();
        String currentUserId = authUser.getUserId();
        if (currentUserId == null) throw new ServiceException(MSG.MAST_LOGIN);

        //是否有资格开会
        SysUser sysUser = sysUserMapper.selectOneById(currentUserId);
        if (!"1".equals(sysUser.getMtAuth())) throw new ServiceException(MSG.USER_MT_NO_AUTH);

        //不存在开启中的会议时才允许创建会议,会议已存在，抛出异常
        QueryWrapper query = QueryWrapper.create().where(MT_ROOM.USER_ID.eq(currentUserId)).where(MT_ROOM.MEETING_STATUS.eq("0")).orderBy(MT_ROOM.ID.desc()).limit(1);
        MtRoom queryOne = mtRoomMapper.selectOneByQuery(query);
        if (queryOne != null) throw new ServiceException(MSG.MT_ROOM_EXISTS);

        //创建会议
        MtRoom mtRoom = new MtRoom();
        mtRoom = ObjectKit.copyTo(param, mtRoom, "title", "content", "passInUserIds", "inPassword", "isBeforeIn", "inType", "isInMute");
        mtRoom.setUserId(currentUserId);
        mtRoom.setMtCode(sysUser.getMtCode());
        mtRoom.setMeetingStatus("0");
        if (StringKit.isBlank(param.getTitle())) mtRoom.setTitle(sysUser.getAccount() + "的会议室");
        mtRoomMapper.insertSelective(mtRoom);

        //TODO 会议创建成功，开启推流连接
        mtRoom.setPushUrl("");
        return mtRoom;
    }

    //结束会议
    @Override
    public boolean closeMtRoom(MtRoom param) {
        String currentUserId = AuthKit.mastLogin().getUserId();

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.where("user_id = ?", currentUserId);

        MtRoom mtRoom1 = new MtRoom();
        mtRoom1.setMeetingStatus("1");

        int i = mtRoomMapper.updateByQuery(mtRoom1, wrapper);

        //TODO 关闭推流连接

        return true;
    }

    //分页查询历史会议
    @Override
    public Page<MtRoom> pageMyHistory(MtRoom param, PageSearch<MtRoom> pageSearch) {
        QueryWrapper where = QueryWrapper.create().where(MT_ROOM.USER_ID.eq(param.getUserId()));
        Page<MtRoom> paginate = mtRoomMapper.paginate(pageSearch, where);
        return paginate;
    }

    @Override
    public boolean nowMyRoomLineUserInfo(MtRoom param) {
        return false;
    }

    @Override
    public MtRoom mtRoomInfoById(String id) {
        QueryWrapper where = QueryWrapper.create().where(MT_ROOM.MT_CODE.eq(id));
        MtRoom mtRoom = mtRoomMapper.selectOneByQuery(where);
        if (mtRoom != null) {
            mtRoom.setInPassword(null);
        }
        return mtRoom;
    }

    @Override
    public MtRoom mtRoomOpenInfoByCode(String code) {
        QueryWrapper where = QueryWrapper.create().where(MT_ROOM.MT_CODE.eq(code)).and(MT_ROOM.MEETING_STATUS.eq("0"));
        MtRoom mtRoom = mtRoomMapper.selectOneByQuery(where);
        if (mtRoom != null) {
            mtRoom.setInPassword(null);
        }
        return mtRoom;
    }

    @Override
    public JSONObject createMtLinkQrCode(String code) {
        String userId = AuthKit.mastLogin().getUserId();
        SysUser sysUser = sysUserMapper.selectOneById(userId);

        String mtCode = sysUser.getMtCode();
        if (StringKit.isNotBlank(code)) {
            mtCode = code;
        }

        //  例子      https://api-buyer.lvtian.info/studioQrCode/?retail=1674975561512910848&studiocode=88888888
        String contents = " https://api-buyer.lvtian.info/tohome/?type=studio&retail=" + userId + "&mtCode=" + mtCode;
        BarcodeFormat barcodeFormat = BarcodeFormat.QR_CODE;
        Integer margin = 2;
        ErrorCorrectionLevel errorLevel = ErrorCorrectionLevel.L;
        String format = "png";
        int width = 200;
        int height = 200;
        String saveImgFilePath = "mtCode_" + userId + ".png";

        boolean success = QrCodeKit.encode(contents, barcodeFormat, margin, errorLevel, format, width, height, saveImgFilePath);
        JSONObject res = new JSONObject();
        if (success) {
            // 读取生成的二维码文件并转换为Base64字符串
            try {
                File qrCodeFile = new File(saveImgFilePath);

                //合成器（指定背景图和输出格式，整个图片的宽高和相关计算依赖于背景图，所以背景图的大小是个基准）
                ImageCombiner combiner = new ImageCombiner(270, 310, Color.WHITE, OutputFormat.PNG);
                //设置整图圆角（输出格式必须为PNG）
                combiner.setCanvasRoundCorner(100);

                //加图片元素
                BufferedImage qrCodeImage = ImageIO.read(qrCodeFile);
                combiner.addImageElement(qrCodeImage, 30, 35);

                //加文本元素
                combiner.addTextElement("会议邀请码:" + mtCode, 20, 80, 260).setCenter(true);

                //执行图片合并
                BufferedImage mtCodeImg = combiner.combine();
                res.put("mtCodeImg", ImageKit.bufferedImageToBase64(mtCodeImg));

                // 删除生成的二维码文件
                Path qrCodePath = qrCodeFile.toPath();
                Files.delete(qrCodePath);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    //    加入会议,并记录日志
    @Override
    public MtRoom inMtRoom(MtRoom param) {
        AuthUser currentUser = AuthKit.mastLogin();

        //查询进行中的会议
        QueryWrapper wrapper = QueryWrapper.create().where(MT_ROOM.MT_CODE.eq(param.getMtCode())).and(MT_ROOM.MEETING_STATUS.eq("0"));
        MtRoom mtRoom = mtRoomMapper.selectOneByQuery(wrapper);
        if (mtRoom == null) throw new ServiceException(MSG.MT_ROOM_IS_CLOSE);

        //检查是否需要密码
        String inPassword = mtRoom.getInPassword();
        if (StringKit.isNotBlank(inPassword) && !inPassword.equals(param.getInPassword()))
            throw new ServiceException(MSG.MT_ROOM_PASSWORD_ERROR);

        //检查是否为部分人可加入,是否在允许加入列表中
        String inType = mtRoom.getInType();
        if ("1".equals(inType)) {
            ArrayList<String> split = StringKit.split(mtRoom.getPassInUserIds());
            if (!split.contains(currentUser.getUserId())) throw new ServiceException(MSG.MT_ROOM_NO_ACCESS);
        }

        //检查主持人是否在会
        String compereStatus = mtRoom.getCompereStatus();
        String isBeforeIn = mtRoom.getIsBeforeIn();
        if ("1".equals(compereStatus) && "1".equals(isBeforeIn)) throw new ServiceException(MSG.MT_ROOM_NOT_BEFORE_IN);

        //异步插入进入会议室记录
        ThreadKit.getPool().execute(() -> {
            MtRoomInOut mtRoomInOut = new MtRoomInOut();
            mtRoomInOut.setInTime(LocalDateTime.now());
            mtRoomInOut.setUserId(currentUser.getUserId());
            mtRoomInOut.setMtRoomId(mtRoom.getId());
            inOutMapper.insert(mtRoomInOut);
        });

        return mtRoom;
    }

    //查询我开启的会议
    @Override
    public MtRoom myOpenMtRoom(MtRoom param) {
        AuthUser currentUser = AuthKit.mastLogin();

        //查询进行中的会议
        QueryWrapper wrapper = QueryWrapper.create().where(MT_ROOM.USER_ID.eq(currentUser.getUserId())).and(MT_ROOM.MEETING_STATUS.eq("0"));
        return mtRoomMapper.selectOneByQuery(wrapper);
    }

    @Override
    public Page<MtRoomApplyVo> page(MtRoomApplyVo mtRoomApply, PageSearch pageSearch) {
        QueryWrapper wrapper = QueryWrapper.create()
                .select(MT_ROOM_APPLY.ALL_COLUMNS).from(MtRoomApply.class)
                .leftJoin(SysUser.class).on(MT_ROOM_APPLY.USER_ID.eq(SYS_USER.ID))
                .select(SYS_USER.ACCOUNT, SYS_USER.ACCOUNT, SYS_USER.PHONE_MOBILE, SYS_USER.ID_CARD_NAME)
                // 根据 用户ID 查询
                .where(MT_ROOM_APPLY.USER_ID.eq(mtRoomApply.getUserId()))
                // 根据用户账号查询
                .and(SYS_USER.ACCOUNT.eq(mtRoomApply.getAccount()))
                // 根据用户手机号查询
                .and(SYS_USER.PHONE_MOBILE.eq(mtRoomApply.getPhoneMobile()))
                // 根据用户身份证姓名查询
                .and(SYS_USER.ID_CARD_NAME.eq(mtRoomApply.getIdCardName()))
                // 根据审批状态查询
                .and(MT_ROOM_APPLY.APPLY_STATUS.eq(mtRoomApply.getApplyStatus()))
                // 审批状态正序
                .orderBy(MT_ROOM_APPLY.APPLY_STATUS.asc())
                // 创建时间倒序
                .orderBy(MT_ROOM_APPLY.CT.desc());
        // 根据申请时间查询
        if (StringKit.isNotBlank(pageSearch.getTime1())) {
            wrapper.and(MT_ROOM_APPLY.CT.between(pageSearch.getTime1().split(",")[0], pageSearch.getTime1().split(",")[1]));
        }
        // 根据审批时间查询
        if (StringKit.isNotBlank(pageSearch.getTime2())) {
            wrapper.and(MT_ROOM_APPLY.UT.between(pageSearch.getTime2().split(",")[0], pageSearch.getTime2().split(",")[1]));
        }

        return mtRoomApplyMapper.paginateAs(pageSearch, wrapper, MtRoomApplyVo.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object approve(MtRoomApply mtRoomApply) {

        //结束时间至少要晚于当前日期 xxx 天
        Date currentDate = new Date();
        // 解析参数中的结束时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date endDate = null;
        try {
            endDate = sdf.parse(mtRoomApply.getApplyCloseTime());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        // 获取 afterDay 天后的日期
        int afterDay = Integer.parseInt(dictService.getString("apply_close_time_after", "0"));
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, afterDay);
        Date afterDaysLater = calendar.getTime();
        // 检查结束时间是否晚于 afterDaysLater
        if (!endDate.after(afterDaysLater)) {
            throw new ServiceException("结束时间至少要晚于当前日期" + afterDay + "天");
        }

        // 修改当前审批 数据
        mtRoomApplyMapper.update(mtRoomApply);

        // 如果是审核通过状态 修改user表 mt_auth
        if ("1".equals(mtRoomApply.getApplyStatus())) {
            // 校验用
            MtRoomApply maCheck = mtRoomApplyMapper.selectOneById(mtRoomApply.getId());
            SysUser sysUser = new SysUser();
            sysUser.setId(maCheck.getUserId());
            sysUser.setMtAuth("1");
            sysUserMapper.update(sysUser);
        }
        
        return true;
    }
}
